
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sychip.fhc.app.wsn.screen


import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.viewModelScope
import com.fhc.base.Async
import com.fhc.base.YMDHMS
import com.fhc.base.ymdHMS
import com.fhc.view.WhileUiSubscribed
import com.sychip.fhc.MainApplication
import com.sychip.fhc.app.data.repo.WsnDeviceRepo
import com.sychip.fhc.app.data.repo.WsnDeviceRssiRepo
import com.sychip.fhc.app.data.repo.WsnTestRecordRepo
import com.sychip.fhc.app.data.source.dto.WsnDeviceRssiDto
import com.sychip.fhc.app.data.source.dto.WsnTestRecordDto
import com.sychip.fhc.app.pref.PrefDataStoreIf
import com.sychip.fhc.app.todo.R
import com.sychip.fhc.app.wsn.nav.WsnUsbStatus
import com.sychip.fhc.base.BaseAppViewModel
import com.sychip.fhc.base.CommonUiState
import com.sychip.fhc.base.UiStatus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.collections.toMutableList


/**
 * ViewModel for the WsnTestHis screen.
 *
 * @property rssiRepo
 * @constructor
 *
 * @param app
 */
@HiltViewModel
class WsnTestHisViewModel @Inject constructor(
    app : MainApplication,
    val prefDataStore: PrefDataStoreIf,
    private val testRepo: WsnTestRecordRepo
) : BaseAppViewModel(app, prefDataStore) {




    /**
     * _rssi filter flow
     */
    private val _testDataFlow:MutableStateFlow<MutableList<WsnTestRecordDto>> = MutableStateFlow( mutableListOf())
    val testDataFlow: StateFlow<MutableList<WsnTestRecordDto>> = _testDataFlow.asStateFlow()

    /**
     * _dev db async
     */
    private val _testDbAsync = testRepo.observeAll(usbId =usbId).map {
            handleRssiAsync(it)
        }.catch { emit(Async.Error(R.string.loading_task_error))
    }

    /**
     * Handle rssi async
     *
     * @param task
     * @return
     */
    private fun handleRssiAsync(task: List<WsnTestRecordDto>?): Async<List<WsnTestRecordDto>> {
        if (task == null) {
            return Async.Error(R.string.task_not_found)
        }
        return Async.Success(task.toMutableList())
    }


    val testAllFlow: StateFlow<CommonUiState<WsnTestRecordDto>> = _testDbAsync.map { task ->
            when (task) {
                Async.Loading -> {
                    _testDataFlow.update { mutableListOf() }
                    CommonUiState(status = UiStatus.Loading)
                }
                is Async.Error ->{
                    _testDataFlow.update { mutableListOf<WsnTestRecordDto>() }
                    CommonUiState( status = UiStatus.Error)
                }
                is Async.Success -> {
                    _testDataFlow.update { task.data.toMutableList()}
                    CommonUiState( status = UiStatus.Success, dataList = task.data)
                }
            }
        }.onCompletion { cause ->
            if (cause == null) _testDataFlow.update { mutableListOf() }
        }.stateIn(
            scope = viewModelScope,
            started = WhileUiSubscribed,
            initialValue = CommonUiState()
        )


    fun deleteAllData() {
        viewModelScope.launch {
            testRepo.deleteAll("")
        }
    }

    fun delete(fromTime:Long) {
        viewModelScope.launch {
            testRepo.deleteByFromTime(fromTime)
        }
    }

}
